﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using OAuth;
using System.Net;

#if ChangedByBehemothTeam
using System.Web.Caching;

using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
#endif

namespace Yammer {
  [XmlRoot]
#if ChangedByBehemothTeam
  [Serializable]
#endif
  public class Settings {

#if ChangedByBehemothTeam

    #region Binary Serialization

    /// <summary>
    /// Serializes to a byte array
    /// </summary>
    /// <returns></returns>
    public byte[] ToByteArray() {
      Object obj = this;
      BinaryFormatter bf = new BinaryFormatter();
      MemoryStream ms = new MemoryStream();
      bf.Serialize(ms, this);
      return ms.ToArray();
    }

    // Convert a byte array to an Object
    public static Settings CreateFromByteArray(byte[] arrBytes) {
      MemoryStream memStream = new MemoryStream();
      BinaryFormatter binForm = new BinaryFormatter();
      memStream.Write(arrBytes, 0, arrBytes.Length);
      memStream.Seek(0, SeekOrigin.Begin);
      Settings obj = (Settings)binForm.Deserialize(memStream);
      return obj;
    }

    #endregion

    public enum StorageType {
      None = 0,
      File = 1,
      WebCache = 2
    }

    private static StorageType _storage = StorageType.None; //Properties.Settings.Default.UseWebCache;
    public static StorageType Storage {
      get { return _storage; }
      set { _storage = value; }
    }
#endif

    public Settings() {
      this.Proxy = new ProxySettings();
      this.OAuth = new OAuthSettings();
    }
    [XmlElement]
    public ProxySettings Proxy { get; set; }
    [XmlElement]
    public OAuthSettings OAuth { get; set; }
    [XmlElement]
    public string UserId { get; set; }

    /// <summary>
    /// Checks if the persisted <see cref="Settings">settings</see> file exists on the client
    /// </summary>
    /// <returns></returns>
    public static Settings CheckConfiguration() {
#if !ChangedByBehemothTeam
          Dictionary<string, DirectoryInfo> appData = Utility.GetAppDirectory();
          if (System.IO.File.Exists(appData["data"] + "\\settings.yam")) {
#endif
#if ChangedByBehemothTeam
      Settings settings = null;
      switch (Storage) {
        case StorageType.WebCache:
          settings = LoadFromCache();
          break;
        case StorageType.File:
          if (!FileExists())
            return null;
          settings = LoadFromFile();
          break;
      }
      if (settings == null)
        return null;
#else
          XmlSerializer serializer = new XmlSerializer(typeof(Settings));
          TextReader reader = new StreamReader(appData["data"] + "\\settings.yam");
          Settings settings = (Settings)serializer.Deserialize(reader);
          reader.Close();
#endif
      if (settings.OAuth.TokenKey != null && settings.OAuth.TokenSecret != null)
        return settings;
      else
        return null;

#if !ChangedByBehemothTeam
            }
            return null;
#endif
    }

    /// <summary>
    /// Saves the <see cref="Settings">settings</see> file to the client
    /// </summary>
    /// <param name="tokenKey"></param>
    /// <param name="tokenSecret"></param>
#if !ChangedByBehemothTeam
    public static void SaveConfiguration(string tokenKey, string tokenSecret, OAuthKey key, WebProxy proxy) {
            Dictionary<string, DirectoryInfo> appData = Utility.GetAppDirectory();
#else
    public static Settings SaveConfiguration(string tokenKey, string tokenSecret, OAuthKey key, WebProxy proxy) {
#endif
            Settings settings = new Settings();
      if (proxy != null && proxy.Address != null) {
        // TODO test this with more significant use of the proxy settings
        settings.Proxy.Address = proxy.Address.ToString();
        NetworkCredential creds = (NetworkCredential)proxy.Credentials;
        settings.Proxy.Id = creds.UserName;
        settings.Proxy.Password = creds.Password;
        settings.Proxy.Enable = true;
      } else
        settings.Proxy.Enable = false;
      key.TokenKey = tokenKey;
      key.TokenSecret = tokenSecret;
      settings.OAuth.TokenKey = tokenKey;
      settings.OAuth.TokenSecret = tokenSecret;

#if ChangedByBehemothTeam
      switch (Storage) {
        case StorageType.WebCache:
          SaveToCache(settings);
          break;
        case StorageType.File:
          SaveToFile(settings);
          break;
      }
      return settings;
#else
            TextWriter writer = new StreamWriter(appData["data"] + "\\settings.yam");
            XmlSerializer serializer = new XmlSerializer(typeof(Settings));
            serializer.Serialize(writer, settings);
            writer.Close();
#endif

    }

#if ChangedByBehemothTeam

    private static bool FileExists() {
      Dictionary<string, DirectoryInfo> appData = Utility.GetAppDirectory();
      return (System.IO.File.Exists(appData["data"] + "\\settings.yam"));
    }
    private static Settings LoadFromFile() {
      Dictionary<string, DirectoryInfo> appData = Utility.GetAppDirectory();
      XmlSerializer serializer = new XmlSerializer(typeof(Settings));
      TextReader reader = new StreamReader(appData["data"] + "\\settings.yam");
      Settings settings = (Settings)serializer.Deserialize(reader);
      reader.Close();
      return settings;
    }
    private static void SaveToFile(Settings settings) {
      Dictionary<string, DirectoryInfo> appData = Utility.GetAppDirectory();
      TextWriter writer = new StreamWriter(appData["data"] + "\\settings.yam");
      XmlSerializer serializer = new XmlSerializer(typeof(Settings));
      serializer.Serialize(writer, settings);
      writer.Close();
    }

    private const string CACHEKEY_YAMMER_SETTINGS = "YammerSettings";
    private static TimeSpan _webCacheExpires = new TimeSpan(1, 0, 0); // 1 hour sliding expiration

    private static Cache GetCache() {
      return System.Web.HttpContext.Current.Cache;
    }
    private static string GetCacheKey() {
      string key = CACHEKEY_YAMMER_SETTINGS;
      string userId = System.Web.HttpContext.Current.User.Identity.Name;
      if (string.IsNullOrEmpty(userId))
        key += "_" + userId;
      return key;
    }

    private static Settings LoadFromCache() {
      Cache webCache = GetCache();
      string key = GetCacheKey();
      //if (webCache[key] = null)
      //  return null;
      return webCache[key] as Settings;
    }
    private static void SaveToCache(Settings settings) {
      Cache webCache = GetCache();
      string key = GetCacheKey();
      if (webCache[key] != null)
        webCache[key] = settings;
      else
        webCache.Add(key, settings, null, Cache.NoAbsoluteExpiration, _webCacheExpires, CacheItemPriority.High, null);
    }

    public static void ClearCache() {
      Cache webCache = GetCache();
      string key = GetCacheKey();
      if (webCache[key] != null)
        webCache.Remove(key);
    }

#endif

  }

#if ChangedByBehemothTeam
  [Serializable]
#endif
  public class ProxySettings {
    [XmlAttribute]
    public bool Enable { get; set; }
    [XmlElement]
    public string Address { get; set; }
    [XmlElement]
    public string Port { get; set; }
    [XmlElement]
    public string Id { get; set; }
    [XmlElement]
    public string Password { get; set; }

  }

#if ChangedByBehemothTeam
  [Serializable]
#endif
  public class OAuthSettings {
    [XmlElement]
    public string TokenKey { get; set; }
    [XmlElement]
    public string TokenSecret { get; set; }
  }
}
